package com.biz.primus.ms.sms.service.provider;

import com.biz.primus.common.utils.JsonUtils;
import com.biz.primus.model.misc.constants.SMSConstants;
import com.biz.primus.model.misc.enums.ApiExceptionType;
import com.biz.primus.model.misc.enums.MessageType;
import com.biz.primus.model.misc.enums.NotAvailableExceptionType;
import com.biz.primus.model.misc.exception.ProviderNotAvailableException;
import com.biz.primus.model.misc.utils.HttpUtils;
import com.biz.primus.model.misc.vo.*;
import com.biz.primus.ms.sms.sdk.yunxin.Base64;
import com.biz.primus.ms.sms.sdk.yunxin.RSA;
import com.biz.primus.ms.sms.service.model.ServiceProvider;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author yanweijin
 * @date 2017/6/23
 */
@Service
@Slf4j
public class AliYunxinSMS implements ServiceProvider {


    @Value("${provider.aliyunxin.private-key}")
    private String privateKey;
    @Value("${provider.aliyunxin.server-key}")
    private String serverKey;
    @Value("${provider.aliyunxin.url}")
    private String url;


    @Override
    public String getProviderId() {
        return "aliYunxin";
    }

    @Override
    public String getProviderName() {
        return "阿里云信";
    }

    @Override
    public boolean isDefaultProvider() {
        return false;
    }


    @Override
    public ProviderResponse massSend(ShortMessageVo... sm) throws UnsupportedOperationException, ProviderNotAvailableException {
        throw new UnsupportedOperationException();
    }

    @Override
    public ProviderResponse massSend(MultiReceiverShortMessageVo multiReciverShortMessage) throws UnsupportedOperationException, ProviderNotAvailableException {
        throw new UnsupportedOperationException();
    }

    @Override
    public long getBalance() throws UnsupportedOperationException, ProviderNotAvailableException {
        return 0;
    }

    @Override
    public void pullDeliveryStateAndPersist() throws UnsupportedOperationException, ProviderNotAvailableException {
        throw new UnsupportedOperationException();
    }

    @Override
    public ProviderResponse send(ShortMessageVo sm) throws ProviderNotAvailableException {


        String tempCode = getTempCode(sm);
        log.info("使用短信模板:{},msg={}", tempCode, sm);
        AliYunxinRequestVo req = new AliYunxinRequestVo(sm, tempCode);
        String rawParams = Joiner.on("&").join(JsonUtils.obj2Json(Lists.newArrayList(req)), serverKey, System.currentTimeMillis());

        HttpPost postRequest = createPostRequest(url, rawParams);
        String resp;
        try {
            resp = HttpUtils.executePostRequest(postRequest);
        } catch (HttpException e) {
            throw new ProviderNotAvailableException(NotAvailableExceptionType.OTHER, e.getMessage());
        }
        log.info("aliyunxin resp = {}", resp);
        AliYunxinResponseVo respVo = JsonUtils.json2Obj(resp, AliYunxinResponseVo.class);
        switch (respVo.getCode()) {
            case 0:
                return new ProviderResponse();
            case 200108:
                return new ProviderResponse(ApiExceptionType.PROVIDER_NOT_AVAILABLE, "余额不足");
            default:
                return new ProviderResponse(ApiExceptionType.PROVIDER_NOT_AVAILABLE, respVo.getMsg());
        }
    }

    private String getTempCode(ShortMessageVo sm) {
        MessageType type = sm.getType();
        if (type == MessageType.auto) {
            type = StringUtils.contains(sm.getContent(), "验证码") ? MessageType.validcode : MessageType.notice;
        }
        if (type == MessageType.validcode) {
            return SMSConstants.SMS_CODE_VALIDATE_CODE;
        }
        if (type == MessageType.notice) {
            return SMSConstants.SMS_CODE_NOTICE;
        }
        return SMSConstants.SMS_CODE_DEFAULT;
    }

    private HttpPost createPostRequest(String url, String rawParams) {
        rawParams = getParams(rawParams);
        String sign = getSign(serverKey, rawParams);
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-type", "application/json");
        post.setEntity(new StringEntity("{\"sign\":\"" + sign + "\",\"params\":\"" + rawParams + "\"}", "UTF-8"));
        post.setHeader("Accept", "application/json");
        return post;
    }


    private String getParams(String params) {
        try {
            byte[] data = params.getBytes();
            byte[] encodedData = RSA.encryptByPrivateKey(data, privateKey);
            return Base64.encode(encodedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getSign(String serverKey, String params) {
        try {
            String sign = RSA.sign(Base64.decode(params), privateKey) + "&" + serverKey;
            sign = Base64.encode(sign.getBytes("UTF-8"));
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
